<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    //demo 1 （使对象变的可观测）
    export class Observe {
        constructor(value) {
            this.value = value;
            def(value, '__ob__', this)
            if (Array.isArray(value)) {
                // value为数组时候的逻辑
                // ...
            }
            else {
                this.walk(value)
            }
        }
        walk(obj) {
            const keys = Object.keys(obj)
            for (let i = 0; i < keys.length; i++) {
                defineReactive(obj, keys[i])
            }
        }
    }
    function defineReactive(obj, value, val) {
        if (arguments.length === 2) {
            val = obj[val]
        }
        if (typeof val === 'object') {
            new Observe(val)
        }
        Object.defineProperty(obj, value, {
            configurable: true,
            enumerable: true,
            get: function () {
                console.log(`${value}被读取了`)
                return val
            },
            set: function (newVal) {
                val = newVal
                console.log(`${value}被修改了`)
            }
        })
    }

    //demo2（收集依赖，此时的依赖暂时用window.target代替）
    export default class Dep {
        constructor() {
            this.subs = []
        }
        addSub(sub) {
            this.subs.push(sub)
        }
        removeSub(sub) {
            this.remove(this.subs, sub)
        }
        depend() {
            if (window.target) {
                this.addSub(window.target)
            }
        }
        notify() {
            const subs = this.subs.slice()
            for (let i = 0; i < this.subs.length; i++) {
                subs[i].update()
            }
        }
    }
    function removeSub(subs, sub) {
        if (subs.length) {
            const index = subs.indexOf(sub)
            if (~index) {
                return this.splice(index, 1)
            }
        }
    }
    function defineReactive(data, key, val) {
        let dep = new Dep();
        Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get: function () {
                dep.depend();
                return val
            },
            set: function (newVal) {
                val = newVal;
                dep.notify();
            }
        })
    }
    //demo3（watcher对象实现）
    export class Watcher {
        constructor(vm, expOrFn, cb) {
            this.vm = vm;
            this.getter = parsePath(expOrFn);
            this.cb = cb;
            this.value = this.get();
        }
        get() {
            window.target = this;
            let value = this.getter.call(this.vm, this.vm);
            window.target = undefined;
            return value
        }
        update() {
            const oldValue = this.value;
            this.value = this.get();
            this.cb.call(this.vm, this.value, oldValue)
        }
    }

    //demo4 修改数组原型方法
    let arrayProto = Array.prototype;
    // 创建一个对象作为拦截器
    export const arrayMethods = Object.create(arrayProto)
    // 改变数组自身内容的7个方法
    const methodsToPatch = [
        'push',
        'pop',
        'shift',
        'unshift',
        'splice',
        'sort',
        'reverse'
    ]
    methodsToPatch.forEach(item=>{
        const original = arrayProto[item] 
    })


</script>

</html>